Skip to content

feat(truapi)!: take chain config from the Trinity stack - #1960

Closed
Mikelle wants to merge 6 commits into
mainfrom
feat/stack-chain-config
Closed

Mikelle wants to merge 6 commits into
mainfrom
feat/stack-chain-config

Conversation

@Mikelle

@Mikelle Mikelle commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

The core reads its chain configuration from the Trinity stack the host runs. A host passes three things: the stack's pointer, the signed descriptor its build bundles, and whether the build allows Polkadot's reserved values (its genesis hashes and the dot TLD). Stack::bundled checks the descriptor against the pointer's key and resolves the network, the TLD, and the Relay, Asset Hub, People and Bulletin genesis hashes. get_chain_info returns the same shape as before with values from the descriptor, and the signing role derives identities under the descriptor's TLD.

The core refuses a stack when:

  • the pointer has no key,
  • the descriptor does not verify under that key,
  • it has no People or Bulletin chain,
  • its TLD is not one the core serves dotNS names under,
  • it uses a reserved value and the build does not allow it.

Expiry is not checked, because nothing fetches a newer copy yet. Refresh is a separate sub-issue of #1312.

Host API

This is a breaking change for every host.

  • Native (UniFFI): HostRuntimeConfig.stack: BundledStack { pointer, descriptor, allowsReservedValues } holds the chain configuration. HostBridge has no supportedChains callback.
  • Browser (@parity/truapi-host): ProductRuntimeConfig.stack: { pointer, descriptor, allowsReservedValues? }. The test host builds a stack from its parts through runtimeConfig.testStack, which only the wasm/testing bundle reads. MockHostConfig.servedChains lists the genesis hashes featureSupported answers from. The major changeset describes the full surface.
  • CLI: builds its stack from the network it resolved. Only the Polkadot network may use reserved values.

What each app build bundles

iOS build Android build Stack Reserved values
Debug, DevCI TESTNET previewnet refused
Nightly, Safetynet NIGHTLY paseo-next-v2 refused
Release PRODUCTION Polkadot (PCF's signed descriptor) allowed

The bundled descriptors are byte-identical copies of the CLI's stacks/ files. iOS reports the network its descriptor declares, so a Release build reports polkadot and a previewnet build reports paseo.

For reviewers

  • Network on previewnet: the previewnet descriptor declares "network": "paseo", so products on previewnet see paseo. dotli reports previewnet today.
  • dotli: dotli lives in another repo and needs its own change to pass stack to @parity/truapi-host/web.
  • Genesis hashes: the apps dial the genesis hashes from their bundled copy, so the Firebase chain registry has to serve chains with those hashes. After a chain wipe, the apps cannot connect until a release ships a fresh copy, or until refresh lands.
  • feat(cli)!: run every network from its stack descriptor #1944: this PR overlaps feat(cli)!: run every network from its stack descriptor #1944 in the CLI's network.rs and main.rs. Whichever lands second resolves a small conflict. Both carry the same Polkadot descriptor bytes.

Testing

  • truapi lib and integration tests pass, and so do the truapi-host-cli integration tests. One truapi-host-cli unit test fails on macOS only, from a /private/var vs /var temp path mismatch outside this change.
  • Clippy on the pinned nightly is clean. make fmt-check is clean. RUSTDOCFLAGS="-D warnings" cargo doc is clean for the default features, mock,test-host and --no-default-features.
  • @parity/truapi-host bun tests pass against freshly built wasm bundles, except wasm-bundle.test.ts. That test reads npm pack --json as an array, which npm 12 no longer prints. The @parity/truapi tests all pass.
  • All three bundled descriptors start the core. Polkadot's is refused unless reserved values are allowed.
  • The TrUAPIHost Swift package and its tests typecheck against regenerated bindings. The iOS app has not been built locally.
  • Android has not been compiled. CI's android-bindings and Android app jobs are its first compile.

Closes #1881

Hosts pass the stack's pointer, the signed descriptor their build
bundles, and whether the build allows Polkadot's reserved values,
instead of genesis hashes, a network suffix and a supportedChains
callback.

- truapi: Stack::bundled verifies the bundled copy against the
  pointer's key and refuses a pointer without one, a descriptor without
  People or Bulletin, a TLD the core does not serve, and Polkadot's
  genesis hashes or `dot` unless the build allows them. Stack::new
  builds one from parts for Rust hosts under the same rules.
- get_chain_info, the People, Bulletin and Asset Hub chains and the
  signing role's TLD come from the stack. Features::supported_chains,
  HostChainSet and HostChainEntry are gone.
- Native: HostRuntimeConfig.stack (BundledStack). Browser:
  runtimeConfig.stack, and runtimeConfig.testStack in the test-host
  bundle.
- CLI: builds its stack from the network it resolved; only Polkadot may
  use reserved values.
- iOS and Android apps bundle the previewnet, paseo-next-v2 and Polkadot
  descriptors and pick one per build.

Closes #1881
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

This pull request touches an app, which is not built by default. Add a label for each build you want:

  • iOS simulator build, ci:ios-simulator: builds the iOS app and attaches a build for the iOS Simulator on a Mac; its unit tests run on every pull request.
  • iOS device build, ci:ios-device: attaches a signed build that installs on a registered iPhone or iPad.
  • Android build, ci:android-device: attaches an APK that installs on an Android phone or an emulator.

Each starts as soon as it is added and follows the branch from then on.

@github-actions github-actions Bot added the size:XXL 1000 lines or more; split it, or say in the description why it cannot be label Nov 6, 2026
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Bundle size report

Compared with main at 566bccd.

Raw Gzip Brotli
truapi-host 8.58 MiB (+81.3 KiB, +0.9%) 5.89 MiB (+29.3 KiB, +0.5%) 5.55 MiB (+18.6 KiB, +0.3%)
truapi-provider 4.04 MiB 1.27 MiB 961.3 KiB
truapi 7.90 MiB 1.10 MiB 917.4 KiB
trinity-stack 634.2 KiB 247.5 KiB 204.8 KiB
Total 21.13 MiB (+81.3 KiB, +0.4%) 8.51 MiB (+29.3 KiB, +0.3%) 7.58 MiB (+18.6 KiB, +0.2%)

WebAssembly modules

Raw Gzip Brotli
truapi-host/wasm/web/truapi_server_bg.wasm 3.46 MiB (+81.5 KiB, +2.4%) 1.20 MiB (+29.4 KiB, +2.5%) 909.8 KiB (+18.7 KiB, +2.1%)
truapi-host/wasm/web/truapi_verifiable_bg.wasm 4.89 MiB 4.64 MiB 4.61 MiB
truapi-provider/truapi_provider_bg.wasm 3.99 MiB 1.26 MiB 953.5 KiB
trinity-stack/wasm/trinity_stack_bg.wasm 564.4 KiB 230.5 KiB 190.0 KiB
Changed files (4)
Raw Gzip Brotli
truapi-host/wasm/web/truapi_server_bg.wasm 3.46 MiB (+81.5 KiB, +2.4%) 1.20 MiB (+29.4 KiB, +2.5%) 909.8 KiB (+18.7 KiB, +2.1%)
truapi-host/generated/host-callbacks-adapter.js 7.1 KiB (-113 B, -1.5%) 1.6 KiB (-25 B, -1.5%) 1.4 KiB (-27 B, -1.9%)
truapi-host/generated/worker-callbacks.js 7.3 KiB (-101 B, -1.3%) 1.5 KiB (-16 B, -1.0%) 1.2 KiB (-15 B, -1.2%)
truapi-host/generated/host-callbacks.js 13.3 KiB (-62 B, -0.5%) 4.1 KiB (-42 B, -1.0%) 3.5 KiB (-38 B, -1.1%)

Commit: e47815c

@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

CI Status: 24 required jobs green, 21 passed and 3 skipped by path filter.

All job results
job result
android-app success
android-bindings success
bundle-size success
changes success
changeset-guard success
cli-package success
codegen success
e2e skipped
explorer success
headless-install success
host-wasm success
ios-app skipped
ios-bindings success
licenses success
playground success
provider-android-bindings success
release-guard success
rust success
ts-client success
ts-debugger success
ts-host success
ts-trinity-stack success
wasm-provider success
workflow-lint skipped

Signing credentials: valid as of 2026-11-06

Commit e47815c0 · run log

The CLI answers get_chain_info with the stack descriptor's network, as an
app bundling the same copy does, and keeps its id only as the product
namespace. It grants Polkadot's reserved values to the network whose
identities are real instead of matching an id a descriptor controls.

Session identity lookup takes the stack's Asset Hub as an Option, so the
all-zero genesis no longer stands for "none". The signing role's test
runtime has no Asset Hub, and the PGAS test that waits on Asset Hub
configures one.

startTestHost and createMockClient take Partial<MockRuntimeConfig>, so a
suite can pass the testStack they read. StackError derives only what is
used.
…uilds

The production wasm bundle reads its stack from a signed descriptor, so the
32-byte hex helpers serve only runtimeConfig.testStack and were dead code,
which -D warnings rejects.
@Mikelle

Mikelle commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

Split into a stack for review, rebased on main and on #1944's CLI:

  1. feat(truapi): resolve a Trinity stack from a signed descriptor #1963 the Stack type
  2. feat(truapi)!: take chain config from the Trinity stack #1964 the core takes its chain configuration from the stack
  3. feat(cli)!: hand the core the stack the CLI resolved #1965 CLI
  4. feat(truapi-host)!: take the stack in ProductRuntimeConfig #1966 @parity/truapi-host and the test host
  5. feat(ios)!: bundle each build's Trinity stack #1967 iOS
  6. feat(android)!: bundle each build's Trinity stack #1968 Android

Each PR's description says how the stack lands.

@Mikelle Mikelle closed this Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1000 lines or more; split it, or say in the description why it cannot be

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trinity stack: take chain config from the stack

1 participant